<?php
/**
 * 表单验证基类.
 *
 * 注入：验证器/异常处理器
 *
 * @author Qiong Wu <papa0924@gmail.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.windframework.com
 *
 * @version $Id: WindEnableValidateModule.php 3904 2013-01-08 07:01:26Z yishuo $
 */
class WindEnableValidateModule
{
    /**
     * 验证类.
     *
     * @var string
     */
    protected $_validatorClass = 'WindValidator';
    /**
     * 错误处理action.
     *
     * @var string
     */
    protected $errorAction = '';
    /**
     * 验证类实例.
     *
     * @var WindValidator
     */
    private $_validator = null;
    /**
     * 验证中产生的错误信息.
     *
     * @var array
     */
    protected $_errors = array();
    /**
     * 验证中产生错误信息时使用的默认错误信息.
     *
     * @var string
     */
    private $_defaultMessage = 'the field validate fail.';

    /**
     * 返回验证中产生的错误信息.
     *
     * @return array $_errors
     */
    public function getErrors()
    {
        return $this->_errors;
    }

    /**
     * 返回验证出错时使用的错误errorAction.
     *
     * errorAction的格式可以用/分割m,c,a三个部分:完整的方式为m/c/a
     *
     * @return string
     */
    public function getErrorAction()
    {
        return $this->errorAction;
    }

    /**
     * 返回验证规则组成的数组.
     *
     * 每一个验证规则都需要如下格式:
     * <code>
     * 	array(
     * 		'field' => 'name',	//验证的字段名
     * 		'default' => 'test',	//如果字段为空
     * 		'args' => array('args1', 'args2'),	//validator验证方法接受的其他参数(必须在被验证参数的后面)
     * 		'validator' => 'isEmpty',	//执行的验证方法(该方法必须在$_validatorClass指向的验证类中存在并可公开访问，并且该方法返回boolean类型)
     * 		'message' => 'name is empty',	//验证失败时返回的错误信息
     * 	)
     * </code>
     * 验证规则可以采用{@link WindUtility::buildValidateRule()}方法进行构造.
     *
     * @return array
     */
    protected function validateRules()
    {
        return array();
    }

    /**
     * 验证方法.
     */
    public function validate()
    {
        $rules = $this->validateRules();
        $methods = get_class_methods($this);
        foreach ((array) $rules as $rule) {
            $getMethod = 'get'.ucfirst($rule['field']);
            $_input = in_array($getMethod, $methods) ? call_user_func(array($this, $getMethod)) : '';
            if (true === $this->check($_input, $rule)) {
                continue;
            }
            $setMethod = 'set'.ucfirst($rule['field']);
            in_array($setMethod, $methods) && call_user_func_array(array($this, $setMethod), array($rule['default']));
        }
    }

    /**
     * 执行rule验证
     *
     * @param string $input 待验证的数据
     * @param array  $rule  数据验证的规则
     *
     * @return bool 如果验证成功返回true,验证失败返回false
     */
    private function check($input, $rule)
    {
        $arg = (array) $rule['args'];
        array_unshift($arg, $input);
        if (call_user_func_array(array($this->getValidator(), $rule['validator']), $arg) !== false) {
            return true;
        }
        if ($rule['default'] === null) {
            $this->_errors[$rule['field']] = $rule['message'];

            return true;
        }

        return false;
    }

    /**
     * 返回验证器.
     *
     * @throws WindException 验证器创建失败抛出异常
     *
     * @return WindValidator
     */
    protected function getValidator()
    {
        if ($this->_validator === null) {
            $_className = Wind::import($this->_validatorClass);
            $this->_validator = WindFactory::createInstance($_className);
            if ($this->_validator === null) {
                throw new WindException('[base.WindEnableValidateModule.getValidator] validator', WindException::ERROR_RETURN_TYPE_ERROR);
            }
        }

        return $this->_validator;
    }
}
